package com.room.search.service;

import com.room.search.core.page.TableDataInfo;
import com.room.search.domain.*;
import com.room.search.domain.enumeration.BkRoomTypeEnum;
import com.room.search.repository.RoomCommunityRepository;
import com.room.search.repository.RoomGoodsRepository;
import com.room.search.repository.RoomListingFeatureRepository;
import com.room.search.repository.RoomUserRepository;
import com.room.search.repository.search.RoomSearchGoodSearchRepository;
import com.room.search.response.RoomResult;
import com.room.search.service.dto.*;
import com.room.search.service.mapper.RoomGoodsMapper;
import com.room.search.util.PageUtils;
import com.room.search.util.UUIDUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Predicate;
import java.util.*;

/**
 * Service Implementation for managing {@link RoomGoods}.
 */
@Service
@Transactional
public class RoomGoodsService {

    private final Logger log = LoggerFactory.getLogger(RoomGoodsService.class);

    private final RoomGoodsRepository roomGoodsRepository;
    private final RoomCommunityRepository communityRepository;
    private final RoomGoodsMapper mapper;
    private final RoomListingFeatureRepository featureRepository;
    private final RoomSupportingFacilitiesService roomSupportingFacilitiesService;
    private final RoomTransactionPropertyService transactionPropertyService;
    private final RoomBasicPropertyService basicPropertyService;
    private final RoomRentBasicService rentBasicService;
    private final RoomSearchGoodSearchRepository roomSearchGoodSearchRepository;
    private final RoomUserRepository userRepository;

    public RoomGoodsService(RoomGoodsRepository roomGoodsRepository,
                            RoomCommunityRepository communityRepository,
                            RoomGoodsMapper mapper,
                            RoomListingFeatureRepository featureRepository,
                            RoomSupportingFacilitiesService roomSupportingFacilitiesService,
                            RoomTransactionPropertyService transactionPropertyService,
                            RoomBasicPropertyService basicPropertyService,
                            RoomRentBasicService rentBasicService,
                            RoomSearchGoodSearchRepository roomSearchGoodSearchRepository, RoomUserRepository userRepository) {
        this.roomGoodsRepository = roomGoodsRepository;
        this.communityRepository = communityRepository;
        this.mapper = mapper;
        this.featureRepository = featureRepository;
        this.roomSupportingFacilitiesService = roomSupportingFacilitiesService;
        this.transactionPropertyService = transactionPropertyService;
        this.basicPropertyService = basicPropertyService;
        this.roomSearchGoodSearchRepository = roomSearchGoodSearchRepository;
        this.rentBasicService = rentBasicService;
        this.userRepository = userRepository;
    }


    /**
     * 分页获取所有房屋
     */
    public TableDataInfo getAllRoom(RoomGoodsDTO dto) {
        Pageable pageable = PageUtils.startPage();
        List<RoomGoods> all = roomGoodsRepository.findAll((root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();

            if (dto.getBkRoomType() != null) {
                predicates.add(criteriaBuilder.equal(root.get("bkRoomType"), dto.getBkRoomType()));
            }

            if (dto.getProvince() != null) {
                predicates.add(criteriaBuilder.equal(root.get("province"), dto.getProvince()));
            }

            if (dto.getCity() != null) {
                predicates.add(criteriaBuilder.equal(root.get("city"), dto.getCity()));
            }

            if (dto.getTitle() != null) {
                predicates.add(criteriaBuilder.like(root.get("title"), "%" + dto.getTitle() + "%"));
            }

            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        });

        List<RoomGoodsDTO> goodsDTOS = mapper.toDto(all);
        Page<RoomGoodsDTO> page = PageUtils.listConvertToPage1(goodsDTOS, pageable);
        return TableDataInfo.getTableDataInfo(page);
    }

    /**
     * 添加房源
     * @param dto 添加房源dto
     */
    @Transactional
    public RoomResult addRoomGoods(AddRoomGoodsDTO dto) {
        log.info("添加房源数据：{}", dto);
        if (dto.getId() != null) {
            return RoomResult.error("有id不能添加房源");
        }

        Long communityId = dto.getCommunityId();
        String bkNo = UUIDUtils.getUuid();

        //找到小区
        RoomCommunity community = communityRepository.findById(communityId).orElse(null);
        if (community == null) {
            return RoomResult.error("无该小区");
        }

        //查找对应小区下是否有相同的房源id的房源
        RoomGoods roomGoods = roomGoodsRepository.findByCommunityAndBkNo(community, bkNo).orElse(new RoomGoods());
        if (roomGoods.getId() != null) {
            return RoomResult.error("已存在该房源了");
        }

        //查询响应的房源特色列表
        List<RoomListingFeature> features = featureRepository.findAllById(dto.getFeatureIds());
        //查找到经纪人
        List<RoomUser> roomUsers = userRepository.findAllById(dto.getRoomUserIds());
        //基本熟悉
        RoomBasicProperty basicProperty = basicPropertyService.save(dto.getBasicProperty());
        //交易熟悉
        RoomTransactionProperty transactionProperty = transactionPropertyService.save(dto.getTransactionProperty());

        roomGoods = mapper
            .toRoomGoodsByAddRoomDTO(dto);
        //基础设施
        if (BkRoomTypeEnum.RENT.equals(dto.getBkRoomType())) {

            RoomSupportingFacilities roomSupportingFacilities = roomSupportingFacilitiesService.save(dto.getSupportingFacility());
            RoomRentBasic rentBasic = rentBasicService.save(dto.getRentBasic());
            roomGoods.setRentBasic(rentBasic);//租房的基础属性
            roomGoods.setSupporting(roomSupportingFacilities);//基础设施
            roomGoods.setRentMethod(dto.getRentMethod());//租房方式
        }


        roomGoods.setBkNo(bkNo)
            .setCommunity(community)
            .setOldprice((dto.getRentPrice() == null ? dto.getSumPrice() : dto.getRentPrice()).toString())
            .setAddress(community.getAddress())
            .setProvince(community.getProvince())
            .setCity(community.getCity())
            .setDistrict(community.getDistrict())
            .setLongitude(community.getLongitude())
            .setLatitude(community.getLatitude())
            .setRoomFeatureIds(features)
            .setRoomUsers(roomUsers)
            .setRoomBasic(basicProperty)//基本熟悉
            .setRoomTransaction(transactionProperty)//交易属性
            .setTitle(dto.getTitle())
            .setCreatedDate(new Date());//创建时间

        RoomGoods saveGoods = roomGoodsRepository.saveAndFlush(roomGoods);
        Long goodsId = saveGoods.getId();

        RoomSearchGood searchGood = roomSearchGoodSearchRepository.findById(goodsId).orElse(new RoomSearchGood());
        if (searchGood.getId()!=null) {
            log.info("ES中已经存在该房源信息，进行修改：{}", searchGood);
        }

        searchGood
            .setGoods_id(goodsId)
            .setBkNo(bkNo)
            .setBk_room_type(saveGoods.getBkRoomType().toString())
            .setCommunityId(communityId)
            .setPrice(dto.getSumPrice())
            .setTransportation(dto.getTransportation())
            .setTitle(dto.getTitle())

            .setArea_price(dto.getAreaPrice())
            .setRent_price(dto.getRentPrice())
            .setBuild_size(Integer.parseInt(basicProperty.getBuildingSize()))
            .setRoom_style(basicProperty.getHouseType())
            .setTowards(basicProperty.getRoomTowards())
            .setFloor(basicProperty.getRoomFloor())
            .setFitment(basicProperty.getRoomFitment());


        roomSearchGoodSearchRepository.save(searchGood);
        return RoomResult.success("添加房源成功");

    }


    /**
     * 根据省份和城市获取响应的房源信息
     */
    public RoomResult getAll(GetAllByProvinceAndCityDTO dto) {
        Pageable pageable = PageRequest.of(0, 4);
        //二手房
        List<RoomGoods> secondRooms = roomGoodsRepository.findAllByProvinceAndCityAndBkRoomType(dto.getProvince(), dto.getCity(), BkRoomTypeEnum.SECOND, pageable);
//        新房
        List<RoomGoods> rentRooms = roomGoodsRepository.findAllByProvinceAndCityAndBkRoomType(dto.getProvince(), dto.getCity(), BkRoomTypeEnum.RENT, pageable);

        List<RoomGoods> newRooms = roomGoodsRepository.findAllByProvinceAndCityAndBkRoomType(dto.getProvince(), dto.getCity(), BkRoomTypeEnum.NEW, pageable);

        //如果不是首页
        if (!dto.isIndex()) {
            return RoomResult.success(new IndexRoomDTO(mapper.toDto(secondRooms), mapper.toDto(rentRooms), mapper.toDto(newRooms)));
        }

        return RoomResult.success(new IndexRoomDTO(fill(mapper.toDto(secondRooms)), fill(mapper.toDto(rentRooms)), fill(mapper.toDto(newRooms))));
    }

    /**
     * 填充新资源
     */
    private List<RoomGoodsDTO> fill(List<RoomGoodsDTO> toDto) {
        int size = toDto.size() - 1;
        if (size != 3) {
            for (int i = 0; i < 3 - size; i++) {
                //如果首页未到4个房源则填充空资源
                toDto.add(new RoomGoodsDTO());
            }
        }
        return toDto;
    }

    /**
     * 根据小区
     */
    public RoomResult getRoomByCommunity(Long communityId) {
        RoomCommunity community = communityRepository.findById(communityId).orElse(null);
        if (community == null) {
            return RoomResult.error("无该小区记录");
        }
        Map<BkRoomTypeEnum, List<RoomGoodsDTO>> result = new HashMap<>();
        for (BkRoomTypeEnum value : BkRoomTypeEnum.values()) {
            List<RoomGoods> all = roomGoodsRepository.findAllByCommunityAndBkRoomType(community, value);
            result.put(value, fill(mapper.toDto(all)));
        }
        return RoomResult.success(new IndexRoomDTO(result.get(BkRoomTypeEnum.SECOND), result.get(BkRoomTypeEnum.RENT), result.get(BkRoomTypeEnum.NEW)));

    }

    /**
     *
     */
    public TableDataInfo getAllRoomByDistrict(CityAndDistrictDTO dto) {
        Pageable pageable = PageRequest.of(0, 4);
        List<RoomGoods> roomGoods = roomGoodsRepository.findAllByCityAndDistrictLikeAndBkRoomType(dto.getCity(), dto.getDistrict() + "%", BkRoomTypeEnum.valueOf(dto.getType()));
        Page<RoomGoods> page = PageUtils.listConvertToPage1(roomGoods, pageable);
        return TableDataInfo.getTableDataInfo(page);
    }

    public RoomResult deleteGoods(Long[] id) {
        roomGoodsRepository.deleteAllById(Arrays.asList(id.clone()));
        return RoomResult.success("删除成功");
    }

}
